/* typehints:start */
import { Npc } from "../../npcs/npc";
/* typehints:end */

import { createLogger } from "../../../core/utils/logging";
import { getArcPoint, getArrRectPoint, makeDiv, waitNextFrame } from "../../../core/utils/utils";
import { Vector } from "../../../core/utils/vector";
import { BaseHUDPart } from "../base_hud_part";
import { SelectBtnGroup } from "../select_btn_group";
import { globalConfig } from "../../../config/global";
import { getDayTime } from "../../time";
import { DynamicDom } from "../dynamic_dom";
import { ClickDetector } from "../../../core/utils/click_detector";

const logger = createLogger('game/parts/world_page')

export class HUDWorldPage extends BaseHUDPart{
  constructor(root){
    super(root);
  }

  createElements(parent){
    this.element = makeDiv(parent, 'world_page', ['hud_page', 'page', 'world_page', 'remove'], `
    <div class="show_items">
      <div class="select_type">
      </div>
      <div class="items">
        <div class="page npc_page">
        </div>
        <div class="page goods_page">
        </div>
      </div>
    </div>
    <div class="information">
      <p>这是一间老旧的木屋。</p>
      <div class="control">
        <div class="styledButton goWorld remove"><img src="res/ui/icons/moveSite.svg" /> <span></span></div>
      </div>
    </div>

    <div class="map">
      <p class="world_title"></p>

      <div class="info">
        <p class="date">天元历: <span>3年6月15日[春]</span></p>
      </div>

      <div class="map_content">
        <svg class="map-line"></svg>
        <div class="grids"></div>
      </div>

      <div class="control">
        <div class="line">
        
        </div>
        <div class="line">
        </div>
      </div>
    </div>
    `);
  }
  
  initialize(){
    this.moveX = 0;
    this.moveY = 0;

    this.currentMapClip = null;
    this.currentMapPos = null;

    this.lines = [];

    // this.domAttach = new DynamicDom(this.root, this.element);

    new SelectBtnGroup(this.root, this.element, '.select_type',
      [
        {
          text: '生灵',
          active: true,
          classType: 'people_btn',
          page: '.items|npc_page'
        },
        {
          text: '物品',
          classType: 'goods_btn',
          page: '.items|goods_page'
        }
      ]
    )
    
    this.handlerMapTouchMove();
    this.handlerControlBtn();

    this.moveWorldPos(this.root.mainPlayer.data.worldPos);

    // setTimeout(() => {
    //   this.root.hud.parts.dialogue.handleAppointDialogue(
    //     this.root.worldMap.getIdNpcs(1)[0],
    //     'a1'
    //   )
    // }, 1000);
    
    this.root.hud.signals.resized.add(this.renderMap.bind(this));
  }

  // 绑定可操作的按钮事件
  handlerControlBtn(){
    let moveWorldBtn = this.element.querySelector('.goWorld');
    
    this.trackClicks(moveWorldBtn, () => {
      let mapSite = this.currentMapClip.map[this.currentMapPos];
      let goWorld = mapSite.attr.goWorld

      // 清除世界中使用的定位，使用玩家自身的定位
      this.currentMapPos = null;
      this.root.mainPlayer.setMapPos(goWorld.mapPos);
      this.moveWorldPos(goWorld.worldPos);
    })
  }

  /**
   * 绑定地图的拖动功能
   */
  handlerMapTouchMove(){
    let map = this.element.querySelector('.map');
    let mapContent = this.element.querySelector('.map_content')
    let touch = new Vector(0, 0);
    let movePos = new Vector(0, 0);
    let mouseDown = false;

    let detector = new ClickDetector(map, {
      captureTouchmove: true,
      applyCssClass: ''
    })

    detector.touchstart.add(pos => {
      touch = new Vector(pos.x, pos.y)
      mapContent.classList.add('no-anim');
      mouseDown = true;
    })
    detector.touchmove.add(pos => {
      if(!mouseDown) return;
      movePos = touch.sub(new Vector(pos.x, pos.y));
      mapContent.style.transform = `translate(${this.moveX - movePos.x}px, ${this.moveY - movePos.y}px)`;
    })
    detector.touchend.add(pos => {
      mouseDown = false;
      this.moveX -= movePos.x;
      this.moveY -= movePos.y;
      movePos = new Vector(0, 0);
      mapContent.classList.remove('no-anim')
    })
    detector.touchout.add(() => {
      detector.touchend.dispatch();
    })
  }

  moveWorldPos(worldPos){
    this.root.gameState.showLoading();

    if(this.currentMapClip){
      this.currentMapClip.onLeave();
    }

    this.root.mainPlayer.setWorldPos(worldPos);
    this.currentMapClip = this.root.worldMap.getMapClip(worldPos);

    if(!this.currentMapClip){
      // assert(false, `${worldPos} 世界区域不存在`)
      // return;
      let dialog = this.root.gameState.dialogs.showWarning('错误', `世界区域[${worldPos}]被删除，你被重新定位至初始区域[0, 0]`);
      dialog.ok.add(() => {
        this.moveWorldPos([0, 0]);
      })
      return;
    } else {
      this.currentMapClip.onEnter();
    }

    this.renderMap().then(() => {
      let mapPos = this.root.mainPlayer.data.mapPos;

      if(!this.currentMapClip.map[mapPos]) mapPos = [0, 0];

      this.root.message('log', '系统', `玩家已抵达<${this.currentMapClip.title}>`, 'world');
      this.moveToMapSite(mapPos, false, true);
    })
  }

  renderMap(){
    return new Promise(resolve => {
      setTimeout(() => {
        waitNextFrame().then(() => {
          // 延迟一下渲染，显示一下好看的加载页面
          setTimeout(() => {
            this.renderMapSite();
            // this.renderLine();
            this.movePlayerPoint();
            this.updateMapLook();
    
            resolve();
            this.root.gameState.hideLoading();
          }, 500);
        })
      }, 0);
    })
  }

  update(){
    let dateDom = this.element.querySelector('.info .date span');

    this.root.time.run('update_date', () => {
      dateDom.innerHTML = this.root.time.getCurrentDateDesc();
    }, getDayTime(), false)
  }

  /**
   * 绘制当前地图的所有地区
   */
  renderMapSite(){
    let map = this.element.querySelector('.map');
    // map.style.height = document.body.offsetHeight - map.offsetTop - 40 + 'px';

    if(!this.currentMapClip) return;
    this.element.querySelector('.world_title').innerText = this.currentMapClip.title;

    let parentMapContent = this.element.querySelector('.map_content .grids');
    let mapSize = globalConfig.map.mapSize;

    parentMapContent.innerHTML = '';

    // 绘制格子来表示地图
    Object.keys(this.currentMapClip.map).map(key => {
      let site = key.split(',');
      let data = this.currentMapClip.map[key];
      let grid = makeDiv(parentMapContent, 'grid_' + site.join(''), ['grid'], `${data.getTitle()}`);

      grid.style.left = site[0] * globalConfig.map.mapSpace.w + 'px';
      grid.style.top = site[1] * globalConfig.map.mapSpace.h + 'px';
      grid.style.width = mapSize.w + 'px';
      grid.style.height = mapSize.h + 'px';

      this.trackClicks(grid, this.moveToMapSite.bind(this, site, true, false), {
        applyCssClass: '',
      });
    });
  }

  /**
   * 更新地图显示的内容
   */
  updateMapLook(){
    if(!this.currentMapPos) return;

    [...this.element.querySelectorAll('.grid')].map(item => {
      item.classList.remove('look');
      item.classList.remove('look_all');
    });

    let lookSiteGroup = [];
    // 根据神识来显示更多的格子，每100就可以多看一圈
    let lookNum = ~~(this.root.mainPlayer.data.attr.cons / globalConfig.player.consLookSite) + 1;

    for(let i = -lookNum; i <= lookNum; i++){
      for(let j = -lookNum; j <= lookNum; j++){
        lookSiteGroup.push([parseInt(this.currentMapPos[0]) + i, parseInt(this.currentMapPos[1]) + j])
      }
    }

    lookSiteGroup.filter(item => this.currentMapClip && this.currentMapClip.map[item]).map(site => {
      this.element.querySelector(`#grid_${site.join('')}`).classList.add('look');
    })

    // 玩家所在site是最完整的site显示
    let currentMapSiteDom = this.element.querySelector(`#grid_${this.currentMapPos.join('')}`);
    if(currentMapSiteDom){
      currentMapSiteDom.classList.add('look_all');
    }

    let currentMapSite = this.currentMapClip.map[this.currentMapPos];

    // 更新当前地图定位的site信息
    let infomration = this.element.querySelector('.information p');
    infomration.innerHTML = `
      ${currentMapSite.getDesc(this.currentMapClip)}
    `;

    let mapLine = this.element.querySelector('.map-line');
    mapLine.innerHTML = '';
    let space = globalConfig.map.mapSpace;
    let size = globalConfig.map.mapSize;

    if(this.currentMapClip){
      // 绘制可移动的指示线条
      currentMapSite.attr.next.map(nextSite => {
        let start = [this.currentMapPos[0] * space.w + size.w / 2 + 5000, this.currentMapPos[1] * space.h + size.h / 2 + 5000];
        let end = [nextSite.pos[0] * space.w + size.w / 2 + 5000, nextSite.pos[1] * space.h + size.h / 2 + 5000];
        let isMove = currentMapSite.isMove(nextSite.pos).flag;
        if(start[0] != end[0] && start[1] != end[1]){
          this.drawSvgArcLine([start, end], isMove);
        } else {
          let line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
          line.setAttribute('x1', start[0]);
          line.setAttribute('y1', start[1]);
          line.setAttribute('x2', end[0]);
          line.setAttribute('y2', end[1]);
  
          line.setAttribute('style', `stroke:${
            isMove ? '#888' : '#f57d7d'
          };stroke-width:2`)
    
          mapLine.appendChild(line);
        }
      });
    }

    this.renderAllPeopleAndGoods();
  }

  drawSvgArcLine(posArr, isMove = true){
    let mapLine = this.element.querySelector('.map-line');
    let path = document.createElementNS('http://www.w3.org/2000/svg', 'path');

    let AnglePos = getArcPoint(posArr[0], posArr[1], 40);
    path.setAttribute('d', `M${posArr[0].join(' ')} Q${AnglePos[0].join(' ')} ${posArr[1].join(' ')}`)
    path.setAttribute('style', `stroke:${
      isMove ? '#888' : '#f57d7d'
    };`)
    mapLine.appendChild(path);
  }

  // TODO 绘制所有的线条，有一个问题，当玩家所在节点不可移动的线条也会显示
  renderLine(){
    let space = globalConfig.map.mapSpace;
    let size = globalConfig.map.mapSize;
    let mapLine = this.element.querySelector('.map-line');
    mapLine.innerHTML = '';

    Object.values(this.currentMapClip.map).map(item => {
      item.attr.next.map(data => {
        let lineData = [item.mapPos, data.pos];
        if(this.isRenderLine(lineData)) return;

        let line = document.createElementNS('http://www.w3.org/2000/svg', 'line');

        line.id = `line_${lineData[0]}_${lineData[1]}`;

        line.setAttribute('x1', lineData[0][0] * space.w + size.w / 2);
        line.setAttribute('y1', lineData[0][1] * space.h + size.h / 2);
        line.setAttribute('x2', lineData[1][0] * space.w + size.w / 2);
        line.setAttribute('y2', lineData[1][1] * space.h + size.h / 2);
  
        line.setAttribute('style', `stroke:${
          item.isMove(data.pos) ? '#888' : '#f57d7d'
        };stroke-width:2`)
  
        mapLine.appendChild(line);
        this.lines.push(lineData);
      })
    })
  }

  isRenderLine(data){
    for(let i = 0; i < this.lines.length; i++){
      let line = this.lines[i];

      if(line[0][0] == data[1][0] && line[0][1] == data[1][1] && 
         line[1][0] == data[0][0] && line[1][1] == data[0][1]){
          return true;
        }
    }

    return false;
  }

  /**
   * 绘制当前区域的所有生灵及物品
   */
  renderAllPeopleAndGoods(){
    this.renderNpc();
    this.renderGood();
  }

  renderNpc(){
    let npcPage = this.element.querySelector('.npc_page');
    let peopleBtnSpan = this.element.querySelector('.people_btn span');
    // let currentMapSite = this.currentMapClip.map[this.currentMapPos];

    npcPage.innerHTML = '';

    // 绘制生灵
    let npcs = this.root.worldMap.getCurrentNpcs().sort(
      /**
       * @param {Npc} a 
       * @param {Npc} b 
       */
      (a, b) => b.battleProgress - a.battleProgress);

    if(npcs.length){
      peopleBtnSpan.innerHTML = npcs.length;

      npcs.map(npc => {
        // npc.setRoot(this.root);

        let npcDom = makeDiv(npcPage, `npc_${npc.people.data._id}`, ['item', 'styledButton', 'white'], `
          <h3>${npc.getName()} <span class="min-text">${npc.people.getFirstIdentity()}</span></h3>
          <p class="progres"><span>0/100</span></p>
        `);
        npc.element = npcDom;

        let npcControl = [
          this.handleShowNpcBoard.bind(this, npc),
          this.handleDialogue.bind(this, npc), 
        ];

        if(this.root.app.setting.getSetting('reverseDialogueAndDetail')){
          npcControl = npcControl.reverse();
        }

        this.trackLongPressAndClick(npcDom, 
          ...npcControl,
          {
            longPressMs: 400
          }
        );
      })

      // if(npcs[0]){
      //   this.handleShowNpcBoard(npcs[0])
      // }
    } else {
      peopleBtnSpan.innerHTML = '';
      npcPage.innerHTML = '<p class="no-look">没有发现此地的任何生灵</p>'
    }
  }

  handleDialogue(npc){
    this.root.hud.parts.dialogue.handleShowDialogue(npc);
  }

  handleShowNpcBoard(npc){
    // this.root.hud.signals.showNpcBoard.dispatch(npc);
    this.root.hud.parts.npcBoard.handleShowNpcBoard(npc);
  }

  renderGood(){
    let goodsBtnSpan = this.element.querySelector('.goods_btn span');
    let goodsPage = this.element.querySelector('.goods_page');
    let goods = this.root.worldMap.getCurrentGoods();
    
    goodsPage.innerHTML = '';

    if(goods.length){
      goodsBtnSpan.innerHTML = goods.length;

      goods.map(item => {
        let goodsDom = makeDiv(goodsPage, null, ['item', 'styledButton', 'white'], `
          <h3>${item.getTitle()} <span class="min-text"></span></h3>
        `);
        item.element = goodsDom;

        this.trackClicks(goodsDom, this.handleShowGoodsBoard.bind(this, item));
      })
    } else {
      goodsBtnSpan.innerHTML = '';

      goodsPage.innerHTML = '<p class="no-look">没有发现此地的任何物品</p>'
    }
  }

  handleShowGoodsBoard(goods){
    this.root.hud.parts.goodsBoard.handleShowGoodsBoard(goods);
  }

  /**
   * 玩家移动到指定地区
   * @param {Array[Number, Number]} pos 
   * @returns 
   */
  moveToMapSite(pos, clickFlag = false, noAnim = false){
    if(this.currentMapPos && pos[0] == this.currentMapPos[0] && pos[1] == this.currentMapPos[1]) {
      this.root.message('alert', '你已经在这里了')
      return;
    }

    if(this.currentMapClip) {
      if(this.currentMapPos){
        const nextSiteFlag = this.currentMapClip.map[this.currentMapPos].isMove(pos);

        if(!nextSiteFlag.flag) {
          this.root.message('alert', nextSiteFlag.text)
          return;
        }
      }

      if(this.currentMapClip.map[this.currentMapPos]){
        this.currentMapClip.map[this.currentMapPos].onLeave();
      }

      this.currentMapPos = pos;
      this.root.mainPlayer.setMapPos(pos);

      let currentMapSite = this.currentMapClip.map[this.currentMapPos];
      currentMapSite.onEnter();
      this.showControlBtn(currentMapSite.attr);
      if(clickFlag) currentMapSite.onClick();
    }

    this.movePlayerPoint(noAnim);
    this.updateMapLook();
  }

  showControlBtn(data){
    let btns = this.element.querySelectorAll('.information .control .styledButton');
    [...btns].map(btn => {
      btn.classList.add('remove');
    })

    Object.keys(data).map(key => {
      if(!data[key]) return;
      let dom = this.element.querySelector(`.${key}`);

      if(dom && dom.classList.contains(key)) {
        if(key === 'goWorld'){
          let mapClip = this.root.worldMap.getMapClip(data[key].worldPos);
          if(!mapClip) return;
          dom.querySelector('span').innerHTML = mapClip.title;
        }
        dom.classList.remove('remove');
      }
    })
  }

  // 移动地图到玩家自身所在地点
  movePlayerPoint(noAnim = false){
    if(!this.currentMapPos) return;

    let map = this.element.querySelector('.map');
    let mapContent = this.element.querySelector('.map_content')
    let currentMapGrid = this.element.querySelector('#grid_' + this.currentMapPos.join(''));
    let mapSize = globalConfig.map.mapSize;

    if(!currentMapGrid) return;

    this.moveX = map.offsetWidth / 2 - currentMapGrid.offsetLeft - mapSize.w / 2;
    this.moveY = map.offsetHeight / 2 - currentMapGrid.offsetTop - mapSize.h / 2;

    if(noAnim){
      mapContent.classList.add('no-anim')
    }
    mapContent.style.transform = `translate(${this.moveX}px, ${this.moveY}px)`;
    waitNextFrame().then(() => {
      mapContent.classList.remove('no-anim')
    })
  }
}